package com.laicunba.service.baofoo;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.laicunba.constant.GloabConstant;
import com.laicunba.service.accounting.impl.FuiouBuyServiceImpl;
import com.laicunba.service.baofoo.rsa.RsaCodingUtil;
import com.laicunba.service.baofoo.util.JXMConvertUtil;
import com.laicunba.service.baofoo.util.MapToXMLString;
import com.laicunba.service.baofoo.util.SecurityUtil;
import com.laicunba.util.AssertUtil;
import com.laicunba.util.StringUtil;

@Service
public class BaofooServiceImpl extends FuiouBuyServiceImpl implements BaofooService {
	private static final Logger LOG = Logger.getLogger(BaofooServiceImpl.class);
	private static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");

	@Transactional
	@Override
	public String buildWapForm(BuildWapFormParam param) {

		AssertUtil.assertNotEmpty(param.txnSubType, "TXN_SUB_TYPE_NOT_EXIST");
		AssertUtil.assertNotEmpty(param.bizType, "BIZ_TYPE_NOT_EXIST");
		AssertUtil.assertNotEmpty(param.payCode, "PAY_CODE_NOT_EXIST");
		AssertUtil.assertNotEmpty(param.accNo, "ACC_NO_NOT_EXIST");
		AssertUtil.assertNotEmpty(param.idCard, "ID_CARD_NOT_EXIST");
		AssertUtil.assertNotEmpty(param.idHolder, "ID_HOLDER_NOT_EXIST");
		AssertUtil.assertNotEmpty(param.mobile, "MOBILE_NOT_EXIST");
		AssertUtil.assertNotEmpty(param.transId, "TRANS_ID_NOT_EXIST");
		AssertUtil.assertNotEmpty(param.txnAmt, "TXN_AMT_NOT_EXIST");
		AssertUtil.assertNotEmpty(param.pageUrl, "PAGE_URL_NOT_EXIST");
		AssertUtil.assertNotEmpty(param.returnUrl, "RETURN_URL_NOT_EXIST");

		Map<Object, Object> encrypMap = new HashMap<Object, Object>();

		encrypMap.put("txn_sub_type", param.txnSubType);
		encrypMap.put("biz_type", param.bizType);
		encrypMap.put("terminal_id", GloabConstant.BAOFOO_TERMINAL_ID);
		encrypMap.put("member_id", GloabConstant.BAOFOO_MEMBER_ID);
		encrypMap.put("pay_code", param.payCode);
		encrypMap.put("acc_no", param.accNo);
		encrypMap.put("id_card_type", param.idCardType);
		encrypMap.put("id_card", param.idCard);
		encrypMap.put("id_holder", param.idHolder);
		encrypMap.put("mobile", param.mobile);
		encrypMap.put("trans_id", param.transId);
		encrypMap.put("txn_amt", param.txnAmt);
		encrypMap.put("trade_date", DATE_FORMAT.format(new Date()));
		encrypMap.put("commodity_name", param.commodityName);
		encrypMap.put("commodity_amount", "1");
		encrypMap.put("user_name", "");
		encrypMap.put("page_url", param.pageUrl);
		encrypMap.put("return_url", param.returnUrl);
		encrypMap.put("additional_info", param.additionalInfo);
		encrypMap.put("req_reserved", param.reqReserved);
		String encrypXml = MapToXMLString.converter(encrypMap, "data_content");
		String base64str = null;
		try {
			base64str = SecurityUtil.Base64Encode(encrypXml);
		} catch (UnsupportedEncodingException e) {
			AssertUtil.assertFail("BASE64_ENCODE_XML_FAIL");
			LOG.error("BASE64_ENCODE_XML_FAIL", e);
		}
		String dataContent = RsaCodingUtil.encryptByPriPfxFile(base64str, GloabConstant.BAOFOO_PFX_FILE, GloabConstant.BAOFOO_PFX_PWD);
		String version = "4.0.0.0";// 版本号
		String inputCharset = "1";
		String language = "1";

		// 商户号
		String txnType = "03311";

		StringBuilder formStr = new StringBuilder();

		formStr.append("<form  name=\"pay\" action=\"").append(GloabConstant.BAOFOO_GW).append("\" method=\"post\">");
		formStr.append("<input name=\"version\" type=\"hidden\" id=\"version\" value=\"").append(version).append("\" />");
		formStr.append("<input name=\"input_charset\" type=\"hidden\" id=\"input_charset\" value=\"").append(inputCharset).append("\" />");
		formStr.append("<input name=\"language\" type=\"hidden\" id=\"language\" value=\"").append(language).append("\" />");
		formStr.append("<input name=\"terminal_id\" type=\"hidden\" id=\"terminal_id\" value=\"").append(GloabConstant.BAOFOO_TERMINAL_ID).append("\" />");
		formStr.append("<input name=\"txn_type\" type=\"hidden\" id=\"txn_type\" value=\"").append(txnType).append("\" />");
		formStr.append("<input name=\"txn_sub_type\" type=\"hidden\" id=\"txn_sub_type\" value=\"").append(param.txnSubType).append("\" />");
		formStr.append("<input name=\"member_id\" type=\"hidden\" id=\"member_id\" value=\"").append(GloabConstant.BAOFOO_MEMBER_ID).append("\" />");
		formStr.append("<input name=\"data_type\" type=\"hidden\" id=\"data_type\" value=\"").append("xml").append("\" />");
		formStr.append("<textarea name=\"data_content\" style=\"display:none;\" id=\"data_content\">").append(dataContent).append("</textarea>");
		formStr.append("<input name=\"back_url\" type=\"hidden\" id=\"back_url\" value=\"").append(param.backUrl).append("\" />");
		formStr.append("</form>");

		return formStr.toString();

	}

	@Transactional
	@Override
	public PayResult parsePayResult(String dataContent) {
		AssertUtil.assertNotEmpty(dataContent, "BAOFOO_RESULT_DATA_CONTENT_EMPTY");
		String decryptDataContent = RsaCodingUtil.decryptByPubCerFile(dataContent, GloabConstant.BAOFOO_CER_FILE);
		AssertUtil.assertNotEmpty(decryptDataContent, "BAOFOO_RESULT_DATA_CONTENT_DECRYPT_EMPTY");
		try {
			decryptDataContent = SecurityUtil.Base64Decode(decryptDataContent);
		} catch (Exception e) {
			AssertUtil.assertFail("BAOFOO_RESULT_DATA_CONTENT_BASE64DECODE_FAIL");
		}
		decryptDataContent = JXMConvertUtil.XmlConvertJson(decryptDataContent);
		Map<String, Object> baofooResponseData = JXMConvertUtil.JsonConvertHashMap(decryptDataContent);
		AssertUtil.assertTrue(baofooResponseData.containsKey("resp_code"), "BAOFOO_RESULT_RESP_CODE_NOT_EXIST");
		PayResult result = new PayResult();
		result.respCode = baofooResponseData.get("resp_code").toString();
		result.respMsg = baofooResponseData.get("resp_msg").toString();
		result.memberId = baofooResponseData.get("member_id").toString();
		result.terminalId = baofooResponseData.get("terminal_id").toString();
		result.dataType = baofooResponseData.get("data_type").toString();
		result.transId = baofooResponseData.get("trans_id").toString();
		result.transNo = baofooResponseData.get("trans_no").toString();
		String succAmt = baofooResponseData.get("succ_amt").toString();
		result.succAmt = StringUtil.isNotEmpty(succAmt) ? BigDecimal.valueOf(Double.parseDouble(succAmt)) : BigDecimal.ZERO;

		return result;
	}

}
